/*
 * Copyright (C) 2005 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.worker;

import java.lang.reflect.Proxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Creates proxy instances to decorate another instance.
 * 
 * @author Johan Maasing
 */
public class WorkerFactory {

    private static Log log = LogFactory.getLog(WorkerFactory.class);

    private WorkerFactory() {
    }

    /**
     * Decorate an instance with a Worker-proxy.
     *
     * @param instance
     *            The object to decorate.
     * @param interfaces
     *            The interfaces the proxy should decorate.
     * @return A proxy object for the instance.
     */
    public static Object decorate(Object instance, Class<?>[] interfaces) {
        if (instance == null) {
            log.trace("Instance to decorate was null, will not decorate.");
            return null;
        } else {
            log.trace("Instantiating WorkerInvocationHandler");
            WorkerInvocationHandler handler = new WorkerInvocationHandler(
                    instance);
            if (log.isTraceEnabled()) {
                for (Class<?> iface : interfaces) {
                    log.trace("Proxying Interface: " + iface.getName());
                }
            }
            return Proxy.newProxyInstance(instance.getClass().getClassLoader(),
                    interfaces, handler);
        }
    }

    /**
     * Decorate an instance with a workerProxy
     *
     * @param instance
     *            The object instance to decorate.
     * @param decoratedInterface
     *            The interface that the proxy should decorate.
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T decorate(Object instance, Class<T> decoratedInterface) {
        log.trace("Instantiating WorkerInvocationHandler for interface: "
                + decoratedInterface);
        WorkerInvocationHandler handler = new WorkerInvocationHandler(instance);
        log.trace("Creating proxy for interface: "
                + decoratedInterface.getName());
        return (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
                new Class[]{decoratedInterface}, handler);
    }

    @SuppressWarnings("unchecked")
    public static <T> T decorate(T instance) {
        log.trace("Retrieving interfaces to decorate");
        @SuppressWarnings("rawtypes")
		Class[] interfaces = instance.getClass().getInterfaces();
        return (T) decorate(instance, interfaces);
    }
}
